diff options
| author | Adam Soltys <[email protected]> | 2024-09-10 20:39:47 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2024-09-17 09:18:36 -0700 |
| commit | 1f63848ca9fb01336f04b41434de1cc06a5b3d93 (patch) | |
| tree | 2affa3041863be365f33d99e1f32bda60cf93a32 /src/routes/(app)/[username]/settings | |
| parent | 6e48c584605bec5623c12c470d04d07303983801 (diff) | |
| download | coinos-ui-1f63848ca9fb01336f04b41434de1cc06a5b3d93.tar.gz coinos-ui-1f63848ca9fb01336f04b41434de1cc06a5b3d93.zip | |
move routes
Diffstat (limited to 'src/routes/(app)/[username]/settings')
6 files changed, 0 insertions, 1132 deletions
diff --git a/src/routes/(app)/[username]/settings/[...tab]/+page.server.ts b/src/routes/(app)/[username]/settings/[...tab]/+page.server.ts deleted file mode 100644 index 42639b38..00000000 --- a/src/routes/(app)/[username]/settings/[...tab]/+page.server.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { fail, redirect } from "@sveltejs/kit"; -import { fd, auth, get, post } from "$lib/utils"; - -export function load({ cookies, params, url }) { - if (url.pathname.endsWith("settings")) - redirect(307, url.pathname + "/account"); - params.cookies = cookies.getAll(); - return { cookies: cookies.getAll(), tab: params.tab }; -} - -export const actions = { - default: async ({ cookies, request }) => { - let form = await fd(request); - - if (form.tab === "pos") { - form.notify = form.notify === "on"; - form.nip5 = form.nip5 === "on"; - form.prompt = form.prompt === "on"; - form.autowithdraw = form.autowithdraw === "on"; - } - - let user = { ...(await get("/me", auth(cookies))), ...form }; - - try { - ({ user } = await post(`/user`, user, auth(cookies))); - } catch (e: any) { - return fail(400, { message: e.message }); - } - - if (user.language) cookies.set("lang", user.language, { path: "/" }); - - return { user, success: true }; - }, -}; diff --git a/src/routes/(app)/[username]/settings/[...tab]/+page.svelte b/src/routes/(app)/[username]/settings/[...tab]/+page.svelte deleted file mode 100644 index 12980291..00000000 --- a/src/routes/(app)/[username]/settings/[...tab]/+page.svelte +++ /dev/null @@ -1,257 +0,0 @@ -<script> - import { browser } from "$app/environment"; - import { onMount, tick } from "svelte"; - import { fly } from "svelte/transition"; - import { applyAction, deserialize } from "$app/forms"; - - import Icon from "$comp/Icon.svelte"; - import Spinner from "$comp/Spinner.svelte"; - import Pin from "$comp/Pin.svelte"; - import { loading, t } from "$lib/translations"; - import { fail, auth, post, sleep, warning, success } from "$lib/utils"; - import { avatar, banner, password, pin } from "$lib/store"; - import { upload } from "$lib/upload"; - import { page } from "$app/stores"; - import { sign, send, reEncryptEntropy, setNsec } from "$lib/nostr"; - import { invalidateAll } from "$app/navigation"; - - import Account from "./_account.svelte"; - import Pos from "./_pos.svelte"; - import Security from "./_security.svelte"; - import Shopify from "./_shopify.svelte"; - - import { PUBLIC_COINOS_URL } from "$env/static/public"; - - export let data; - export let form; - - let submit; - let formElement; - - let { user, token, rates, tab, cookies } = data; - let prev; - - $: update(data); - let update = () => { - ({ user, token, rates, tab } = data); - prev = { ...user }; - }; - - $: form?.user && ({ user } = form); - - $: form?.success && throttledSuccess(); - - let justUpdated; - let throttledSuccess = () => { - if (!justUpdated) { - justUpdated = true; - success($t("user.settings.saved"), false); - setTimeout(() => (justUpdated = false), 5000); - } - }; - - $: form?.message && fail(form.message); - - $: if (form?.message?.startsWith("Pin")) { - fail("Wrong pin, try again"); - $pin = ""; - } - - let tabs = [ - { name: "account", key: "ACCOUNT", comp: Account }, - { name: "pos", key: "POINT_OF_SALE", comp: Pos }, - { name: "security", key: "SECURITY", comp: Security }, - { name: "shopify", key: "SHOPIFY", comp: Shopify }, - ]; - - $: ({ comp } = tabs.find((t) => t.name === tab)); - - let { address, id, username } = user; - let submitting; - - $: if (!$loading && $page.url.searchParams.get("verified")) - success($t("user.settings.verified")); - - async function handleSubmit() { - try { - submitting = true; - let data = new FormData(formElement); - - if (data.get("newNsec")) { - await setNsec(user, data.get("newNsec")); - data.set("nsec", user.nsec); - data.set("pubkey", user.pubkey); - } - - if (data.get("password")) { - try { - data.set( - "cipher", - await reEncryptEntropy(user, data.get("password")) - ); - } catch (e) { - console.log("Failed to encrypt keys with new password"); - throw e; - } - } - - if ($avatar) { - try { - let { hash } = JSON.parse( - await upload($avatar.file, $avatar.type, $avatar.progress, token) - ); - - data.set("profile", hash); - - await fetch(`/api/public/${hash}.webp`, { - cache: "reload", - mode: "no-cors", - }); - } catch (e) { - console.log("problem upsubmitting avatar", e); - } - } - - if ($banner) { - try { - let { hash } = JSON.parse( - await upload($banner.file, $banner.type, $banner.progress, token) - ); - - data.set("banner", hash); - - await fetch(`/api/public/${hash}.webp`, { - cache: "reload", - mode: "no-cors", - }); - } catch (e) { - console.log("problem upsubmitting banner", e); - } - } - - if (["username", "address", "profile"].some((a) => user[a] !== prev[a])) { - let event = { - pubkey: user.pubkey, - created_at: Math.floor(Date.now() / 1000), - kind: 0, - content: JSON.stringify({ - name: user.username, - about: user.address, - picture: `${PUBLIC_COINOS_URL}/public/${user.profile}.webp`, - }), - tags: [], - }; - - try { - await sign({ event, user }); - await send(event); - } catch (e) { - warning("Nostr profile could not be updated"); - } - } - - if (user.email !== prev.email) { - try { - cookies.get = function (n) { - return this.find((c) => c.name === n).value; - }; - - user.verified = false; - - await post( - "/api/request", - { id: user.id, email: user.email }, - auth(cookies) - ); - - warning($t("user.settings.verifying"), false); - } catch (e) { - fail(e.message); - console.log(e); - } - } - - const response = await fetch(formElement.action, { - method: "POST", - body: data, - }); - - const result = deserialize(await response.text()); - - if (result.type === "success") { - await invalidateAll(); - if (data.get("password")) $password = data.get("password"); - } - - applyAction(result); - } catch (e) { - console.log(e); - fail("Something went wrong"); - } - - submitting = false; - } -</script> - -{#if user.haspin && $pin?.length !== 6} - <Pin /> -{/if} - -<form - method="POST" - class="mb-[154px] settings" - on:submit|preventDefault={handleSubmit} - bind:this={formElement} -> - <input type="hidden" name="pin" value={$pin} /> - <input type="hidden" name="tab" value={tab} /> - - <div class="mt-24 mb-20 px-3 md:px-0 w-full md:w-[400px] mx-auto space-y-8"> - <div class="header"> - <h1 class="text-center text-3xl md:text-4xl font-semibold mb-10"> - {$t("user.settings.header")} - </h1> - - <div - class="font-bold flex justify-around items-center border-b pb-3 text-secondary" - > - {#each tabs.filter((t) => t.name !== "shopify") as { name, key }} - <a href={`/${user.username}/settings/${name}`}> - <button - type="button" - class="hover:opacity-80" - class:text-black={tab === name || - (tab === "shopify" && name === "pos")} - >{$t(`user.settings.${key}`)}</button - > - </a> - {/each} - </div> - </div> - - <svelte:component this={comp} {user} {rates} {submit} /> - </div> - - <div - class="z-10 fixed bottom-0 bg-white shadow border-t w-full flex justify-center items-center py-3" - > - <button - bind:this={submit} - type="submit" - class="border-2 border-black rounded-xl font-semibold mx-auto py-3 w-40 hover:opacity-80" - class:bg-black={submitting} - > - {#if submitting} - <Spinner /> - {:else} - <div class="my-auto">{$t("user.settings.saveSettings")}</div> - {/if} - </button> - </div> -</form> - -<style> - .settings { - view-transition-name: settings; - } -</style> diff --git a/src/routes/(app)/[username]/settings/[...tab]/_account.svelte b/src/routes/(app)/[username]/settings/[...tab]/_account.svelte deleted file mode 100644 index 8e3323c7..00000000 --- a/src/routes/(app)/[username]/settings/[...tab]/_account.svelte +++ /dev/null @@ -1,190 +0,0 @@ -<script> - import { tick } from "svelte"; - import { avatar, banner } from "$lib/store"; - import Icon from "$comp/Icon.svelte"; - import { t } from "$lib/translations"; - import { page } from "$app/stores"; - - export let user, rates, submit; - - let { id } = user; - - let avatarFile, avatarInput, bannerFile, bannerInput; - - let selectAvatar = () => avatarInput.click(); - let selectBanner = () => bannerInput.click(); - - let percent; - let progress = async (event) => { - percent = Math.round((event.loaded / event.total) * 100); - }; - - let tooLarge = {}; - - let handleFile = async ({ target }, type) => { - tooLarge[type] = false; - let file = target.files[0]; - if (!file) return; - - if (file.size > 10000000) return (tooLarge[type] = true); - - if (type === "profile") { - $avatar = { id, file, type, progress }; - } else if (type === "banner") { - $banner = { id, file, type, progress }; - } - - var reader = new FileReader(); - reader.onload = async (e) => { - if (type === "profile") { - $avatar.src = e.target.result; - } else if (type === "banner") { - $banner.src = e.target.result; - } - }; - - reader.readAsDataURL(file); - }; - - if (!user.display) user.display = user.username; - - $: url = `${$page.url.host}/${user.username}`; - $: full = `${$page.url.protocol}//${url}`; - $: addr = `${user.username}@${$page.url.host}`; -</script> - -<div> - <label for="username" class="font-bold mb-1 block" - >{$t("user.settings.username")}</label - > - <div class="flex mb-2"> - <input - type="text" - name="username" - bind:value={user.username} - class="w-auto min-w-0 pr-1 grow" - /> - </div> -</div> - -<div> - <label for="display" class="font-bold mb-1 block" - >{$t("user.settings.displayName")}</label - > - <input type="text" name="display" bind:value={user.display} /> -</div> - -<div class="space-y-1 relative"> - <label for="email" class="font-bold block">{$t("user.settings.email")}</label> - <p class="text-secondary"> - {$t("user.settings.emailDescription")} - </p> - - <div class="relative"> - <input type="text" name="email" bind:value={user.email} /> - {#if user.verified} - <Icon icon="check" style="absolute right-5 top-3 w-8" /> - {:else if user.email} - <Icon icon="orangeclock" style="absolute right-5 top-3 w-8" /> - {/if} - </div> -</div> - -<div> - <span class="font-bold">{$t("user.settings.profileImage")}</span> - - <div class="flex"> - {#if $avatar || user.profile} - <div - class="relative rounded-full overflow-hidden text-center w-20 h-20 my-auto hover:opacity-80 cursor-pointer" - on:click={selectAvatar} - on:keydown={selectAvatar} - > - <img - src={$avatar?.src || `/api/public/${user.profile}.webp`} - class="absolute w-full h-full object-cover object-center visible overflow-hidden" - alt={user.username} - /> - </div> - {:else} - <div - class="rounded-full border-4 border-white p-4 bg-gradient-to-r from-primary to-gradient w-24 my-auto hover:opacity-80 cursor-pointer" - on:click={selectAvatar} - on:keydown={selectAvatar} - > - <Icon icon="logo-symbol-white" style="mx-auto" /> - </div> - {/if} - <div class="ml-2 p-2"> - <!-- found missing translation --> - <button - type="button" - class="border rounded-2xl font-bold w-24 text-center px-0 py-2 hover:opacity-80" - on:click={selectAvatar} - on:keydown={selectAvatar}>{$t("user.settings.select")}</button - > - <input - type="file" - class="hidden" - bind:this={avatarInput} - on:change={(e) => handleFile(e, "profile")} - /> - </div> - </div> - - {#if tooLarge["avatar"]} - <div class="text-red-600">Max file size 10MB</div> - {/if} -</div> - -<div> - <div class="flex justify-between items-center"> - <span class="font-bold">{$t("user.settings.bannerImage")}</span> - </div> - - {#if $banner || user.banner} - <img - src={$banner ? $banner.src : `/api/public/${user.banner}.webp`} - class="w-full object-cover object-center visible overflow-hidden h-48 mb-4 hover:opacity-80" - on:click={selectBanner} - on:keydown={selectBanner} - alt="Banner" - /> - {:else} - <div - class="bg-gradient-to-r from-primary to-gradient w-full h-48 mb-4 cursor-pointer hover:opacity-80" - on:click={selectBanner} - on:keydown={selectBanner} - alt="Banner" - /> - {/if} - - <button - type="button" - class="border rounded-2xl font-bold w-24 text-center px-0 py-2 hover:opacity-80" - on:click={selectBanner} - on:keydown={selectBanner}>{$t("user.settings.select")}</button - > - <input - type="file" - class="hidden" - bind:this={bannerInput} - on:change={(e) => handleFile(e, "banner")} - /> - - {#if tooLarge["banner"]} - <div class="text-red-600">Max file size 10MB</div> - {/if} -</div> - -<div> - <label for="address" class="font-bold mb-1 block" - >{$t("user.settings.about")}</label - > - <textarea - type="text" - name="address" - bind:value={user.address} - placeholder={$t("user.settings.aboutPlaceholder")} - /> -</div> diff --git a/src/routes/(app)/[username]/settings/[...tab]/_pos.svelte b/src/routes/(app)/[username]/settings/[...tab]/_pos.svelte deleted file mode 100644 index 6a1c92a1..00000000 --- a/src/routes/(app)/[username]/settings/[...tab]/_pos.svelte +++ /dev/null @@ -1,238 +0,0 @@ -<script> - import { tick } from "svelte"; - import Icon from "$comp/Icon.svelte"; - import Numpad from "$comp/Numpad.svelte"; - import LocaleSelector from "$comp/LocaleSelector.svelte"; - import Toggle from "$comp/Toggle.svelte"; - import { locale, t } from "$lib/translations"; - import { success, fail } from "$lib/utils"; - import { page } from "$app/stores"; - - export let user, rates, submit; - - let { currency } = user; - let rate = rates[currency]; - - let fiats = Object.keys(rates).sort((a,b) => a.localeCompare(b)); - $: user.language = $locale; - let keypress = (e) => e.key === "Enter" && (e.preventDefault() || el.click()); - - let editingReserve, editingThreshold, doneReserve, doneThreshold; - let doneEditing = () => { - editingReserve = false; - editingThreshold = false; - }; - - let editReserve = async () => { - editingReserve = true; - await tick(); - reserveEl.focus(); - }; - - let editThreshold = async () => { - editingThreshold = true; - await tick(); - thresholdEl.focus(); - }; - - if (!user.threshold) user.threshold = 1000000; - if (!user.reserve) user.reserve = 100000; - let reserveEl, thresholdEl; -</script> - -<div> - <label for="language" class="font-bold block mb-1" - >{$t("user.settings.locale")}</label - > - <LocaleSelector style="select-styles block py-3 w-full" /> -</div> - -<div> - <label for="currency" class="font-bold block mb-1" - >{$t("user.settings.localCurrency")}</label - > - <select - name="currency" - class="select-styles block py-3 w-full" - value={user.currency} - > - {#each fiats as fiat} - <option value={fiat}>{fiat}</option> - {/each} - </select> -</div> - -<div> - <label for="memoPrompt" class="font-bold mb-1 block" - >{$t("user.settings.memoPrompt")}</label - > - <textarea - name="memoPrompt" - placeholder={$t("user.settings.memoPromptPlaceholder")} - bind:value={user.memoPrompt} - /> -</div> - -<div> - <div class="flex justify-between items-center"> - <span class="font-bold">{$t("user.settings.notifications")}</span> - <Toggle id="notify" bind:value={user.notify} /> - </div> - <p class="text-secondary mt-1 w-9/12"> - {$t("user.settings.notificationsDesc")} - </p> -</div> - -<div> - <div class="flex justify-between items-center"> - <span class="font-bold">{$t("user.settings.tipPrompt")}</span> - <Toggle id="prompt" bind:value={user.prompt} /> - </div> - <p class="text-secondary mt-1 w-9/12"> - {$t("user.settings.tipPromptDescription")} - </p> -</div> - -<div> - <div class="flex justify-between items-center"> - <span class="font-bold">{$t("user.settings.publishNip5")}</span> - <Toggle id="nip5" bind:value={user.nip5} /> - </div> - <p class="text-secondary mt-1 w-9/12"> - {$t("user.settings.nip5a")} - <span class="font-bold">{user.username}@{$page.url.host}</span> - {$t("user.settings.nip5b")} - </p> -</div> - -<div> - <div class="flex justify-between items-center"> - <span class="font-bold">{$t("user.settings.autoWithdraw")}</span> - <Toggle id="autowithdraw" bind:value={user.autowithdraw} /> - </div> - <p class="text-secondary mt-1 w-9/12"> - {$t("user.settings.autoWithdrawDescription")} - </p> -</div> - -{#if user.autowithdraw} - <div class="mb-2"> - <label for="display" class="font-bold mb-1 block" - >{$t("user.settings.destination")}</label - > - <textarea - name="destination" - placeholder={$t("user.settings.destinationPlaceholder")} - on:keypress={keypress} - class="w-full p-4 border rounded-xl h-48" - bind:value={user.destination} - /> - </div> - - <div> - <label for="display" class="font-bold mb-1 block" - >{$t("user.settings.threshold")}</label - > - <button type="button" class="flex w-full" on:click={editThreshold}> - <div class="p-4 border rounded-2xl rounded-r-none border-r-0 bg-primary"> - ⚡️ - </div> - <div - class="border-l-0 rounded-l-none pl-2 w-full p-4 border rounded-2xl text-left" - > - {user.threshold} - </div> - <input type="hidden" name="threshold" bind:value={user.threshold} /> - </button> - <p class="text-secondary mt-1"> - {$t("user.settings.thresholdDesc")} - </p> - </div> - - <div> - <label for="display" class="font-bold mb-1 block" - >{$t("user.settings.reserve")}</label - > - <button type="button" class="flex w-full" on:click={editReserve}> - <div class="p-4 border rounded-2xl rounded-r-none border-r-0 bg-primary"> - ⚡️ - </div> - <div - class="border-l-0 rounded-l-none pl-2 w-full p-4 border rounded-2xl text-left" - > - {user.reserve} - </div> - <input type="hidden" name="reserve" bind:value={user.reserve} /> - </button> - <p class="text-secondary mt-1"> - {$t("user.settings.reserveDesc")} - </p> - </div> -{/if} - -{#if editingThreshold} - <div - class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50" - > - <div - class="relative top-40 mx-auto p-5 border shadow-lg rounded-md bg-white space-y-5 w-lg max-w-lg" - > - <h1 class="text-center text-2xl font-semibold"> - {$t("user.settings.threshold")} - </h1> - <Numpad - bind:amount={user.threshold} - bind:currency - bind:rate - bind:submit={doneReserve} - bind:element={thresholdEl} - /> - - <button - bind:this={doneReserve} - type="button" - on:click={doneEditing} - class="p-4 bg-black text-white rounded-2xl text-lg font-semibold w-full" - >Ok</button - > - </div> - </div> -{/if} - -{#if editingReserve} - <div - class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50" - > - <div - class="relative top-40 mx-auto p-5 border shadow-lg rounded-md bg-white space-y-5 w-lg max-w-lg text-center" - > - <h1 class="text-2xl font-semibold"> - {$t("user.settings.reserve")} - </h1> - <Numpad - bind:amount={user.reserve} - bind:currency - bind:rate - bind:submit={doneReserve} - bind:element={reserveEl} - /> - <button - bind:this={doneReserve} - type="button" - on:click={doneEditing} - class="p-4 bg-black text-white rounded-2xl text-lg font-semibold w-full" - >Ok</button - > - </div> - </div> -{/if} - -<a href="./shopify"> - <button - type="button" - class="flex rounded-full border py-2 px-4 font-bold hover:opacity-80 w-full gap-2 my-5 justify-center" - > - <img src="/icons/shopify.svg" class="w-8" /> - <div class="my-auto">{$t("user.settings.shopify")}</div> - </button> -</a> diff --git a/src/routes/(app)/[username]/settings/[...tab]/_security.svelte b/src/routes/(app)/[username]/settings/[...tab]/_security.svelte deleted file mode 100644 index 6b44f830..00000000 --- a/src/routes/(app)/[username]/settings/[...tab]/_security.svelte +++ /dev/null @@ -1,321 +0,0 @@ -<script> - import { getMnemonic, getNsec } from "$lib/nostr"; - import { tick } from "svelte"; - import { t } from "$lib/translations"; - import Pin from "$comp/Pin.svelte"; - import Icon from "$comp/Icon.svelte"; - import Qr from "$comp/Qr.svelte"; - import { copy, post, success, fail } from "$lib/utils"; - import { pin as current } from "$lib/store"; - import { invalidate } from "$app/navigation"; - import { page } from "$app/stores"; - - export let user, rates, submit; - - let confirming2fa, - disabling2fa, - importing, - locked, - mnemonic, - newNsec, - nsec, - old, - otp, - password, - pin, - revealPassword, - revealSeed, - revealNsec, - token = "", - setting2fa, - settingPin, - verify; - - let toggleImporting = () => { - revealNsec = false; - importing = !importing; - }; - - let toggleNsec = async () => { - try { - nsec = await getNsec(user); - revealNsec = !revealNsec; - importing = false; - } catch (e) { - console.log(e); - } - }; - - let togglePassword = () => (revealPassword = !revealPassword); - let toggleSeed = async () => { - try { - mnemonic = await getMnemonic(user); - revealSeed = !revealSeed; - } catch (e) { - console.log(e); - } - }; - - $: verifying = pin?.length > 5; - $: verify && checkPin(pin); - let checkPin = async () => { - old = $current; - - try { - if (pin.length > 5 && pin === verify) { - user.haspin = true; - $current = pin; - pin = ""; - verify = ""; - submit.click(); - settingPin = false; - verifying = false; - } else { - fail("Pin mismatch, try again"); - pin = ""; - verify = ""; - verifying = false; - settingPin = true; - } - } catch (e) { - console.log(e); - fail("Problem setting PIN"); - } - }; - - let reset = () => { - token = ""; - return true; - }; - - let disablingPin = false; - - let togglePin = async () => { - if (user.haspin) { - try { - disablingPin = true; - await tick(); - submit.click(); - } catch (e) { - console.log(e); - fail("Failed to disable pin"); - } - } else { - settingPin = true; - disablingPin = false; - } - }; - - let startEnabling2fa = async () => { - reset(); - try { - if (!otp) otp = await post("/otpsecret", { pin: $current }); - } catch (e) { - console.log(e); - } - - setting2fa = true; - }; - - let startDisabling2fa = () => (disabling2fa = true); - let startConfirming2fa = () => (confirming2fa = true); - let cancel = () => { - pin = null; - token = null; - verifying = false; - settingPin = false; - setting2fa = false; - confirming2fa = false; - disabling2fa = false; - }; - - $: enable2fa(token); - let enable2fa = async (twoFa) => { - try { - if (setting2fa && token.length === 6) { - await post("/enable2fa", { token }); - success("2FA enabled"); - user.twofa = 1; - cancel(); - } - } catch (e) { - fail("Failed to enable 2FA, try again"); - } - }; - - $: disable2fa(token); - let disable2fa = async () => { - try { - if (disabling2fa && token.length === 6) { - await post("/disable2fa", { token }); - success("2FA disabled"); - delete user.twofa; - disabling2fa = false; - } - } catch (e) { - console.log(e); - fail("Failed to disable 2FA, try again"); - } - }; -</script> - -<input type="hidden" name="newpin" value={disablingPin ? "delete" : pin} /> -<input type="hidden" name="confirm" bind:value={password} /> - -<div class="relative mb-5"> - <label for="password" class="block font-bold block mb-1" - >{$t("user.settings.newPassword")}</label - > - {#if revealPassword} - <input name="password" type="text" bind:value={password} /> - {:else} - <input name="password" type="password" bind:value={password} /> - {/if} - <button - type="button" - on:click={togglePassword} - on:keydown={togglePassword} - class="absolute right-5 top-11" - > - <Icon icon={revealPassword ? "eye" : "eye-off"} /> - </button> -</div> - -<div> - <span class="font-bold mb-1" - >{verifying - ? $t("user.settings.verifyPIN") - : $t("user.settings.securityPIN")}</span - > - <p class="text-secondary mb-1"> - {$t("user.settings.securityPINDescription")} - </p> - {#if verifying} - <Pin bind:value={verify} {cancel} notify={false} /> - {:else if settingPin} - <Pin - bind:value={pin} - title={$t("user.settings.setPIN")} - {cancel} - notify={false} - /> - {:else} - <button type="button" class="primary" on:click={togglePin} - ><Icon icon="lock" style="mr-1" /> - {user.haspin - ? $t("user.settings.disablePIN") - : $t("user.settings.enablePIN")}</button - > - {/if} -</div> - -<div> - <span class="font-bold mb-1">{$t("user.settings.twofa")}</span> - <p class="text-secondary mb-4"> - {$t("user.settings.twofaDescription")} - </p> - - {#if setting2fa} - <a href={otp.uri}> - <Qr src={otp.qr} /> - </a> - - <div class="text-center my-4"> - {$t("user.settings.accountId")}<br /> - <b>{otp.secret}</b> - </div> - - <button type="button" class="primary" on:click={startConfirming2fa}> - <Icon icon="numpad" style="w-8 mr-1" /> - <div class="my-auto">Confirm</div> - </button> - {:else if user.twofa} - <button type="button" class="primary" on:click={startDisabling2fa}> - <Icon icon="mobile" style="w-8 mr-1" /> - <div class="my-auto">{$t("user.settings.twofaDisable")}</div> - </button> - {:else} - <button type="button" class="primary" on:click={startEnabling2fa}> - <Icon icon="mobile" style="w-8 mr-1" /> - <div class="my-auto">{$t("user.settings.twofaSetup")}</div> - </button> - {/if} - - {#if confirming2fa || disabling2fa} - <Pin - bind:value={token} - title="Enter 2FA Code" - {cancel} - persist={false} - notify={false} - /> - {/if} -</div> - -<!-- <div> --> -<!-- <label for="seedphrase" class="font-bold" --> -<!-- >{$t("user.settings.seedPhrase")}</label --> -<!-- > --> -<!-- --> -<!-- <p class="text-secondary mb-1"> --> -<!-- {$t("user.settings.seedDescription")} --> -<!-- </p> --> -<!-- --> -<!-- <button type="button" class="primary" on:click={toggleSeed}> --> -<!-- <Icon icon="warning" style="mr-1 w-6 my-auto" /> --> -<!-- {revealSeed ? $t("user.settings.hideSeed") : $t("user.settings.revealSeed")} --> -<!-- </button> --> -<!-- --> -<!-- {#if revealSeed} --> -<!-- <div class="text-lg"> --> -<!-- {mnemonic} --> -<!-- </div> --> -<!-- --> -<!-- <button type="button" class="primary" on:click={() => copy(mnemonic)}> --> -<!-- <Icon icon="copy" style="mr-1 w-6 my-auto" /> --> -<!-- Copy --> -<!-- </button> --> -<!-- {/if} --> -<!-- </div> --> - -<div> - <label for="seedphrase" class="font-bold" - >{$t("user.settings.nostrKeys")}</label - > - - <p class="text-secondary mb-1"> - {$t("user.settings.nostrDescription")} - </p> - - <div class="flex"> - <button type="button" class="primary" on:click={toggleNsec}> - {#if revealNsec} - <Icon icon="eye-off" style="mr-1 w-6 my-auto" /> - {$t("user.settings.hideNsec")} - {:else} - <Icon icon="warning" style="mr-1 w-6 my-auto" /> - {$t("user.settings.revealNsec")} - {/if} - </button> - - <button type="button" class="primary" on:click={toggleImporting}> - <Icon icon="save" style="mr-1 w-6 my-auto" /> - {$t("user.settings.import")} - </button> - </div> - - {#if importing} - <input name="newNsec" bind:value={newNsec} placeholder="nsec..." /> - {/if} - - {#if revealNsec} - <div class="text-lg break-all"> - {nsec} - </div> - - <button type="button" class="primary" on:click={() => copy(nsec)}> - <Icon icon="copy" style="mr-1 w-6 my-auto" /> - Copy - </button> - {/if} -</div> diff --git a/src/routes/(app)/[username]/settings/[...tab]/_shopify.svelte b/src/routes/(app)/[username]/settings/[...tab]/_shopify.svelte deleted file mode 100644 index 0266fa9c..00000000 --- a/src/routes/(app)/[username]/settings/[...tab]/_shopify.svelte +++ /dev/null @@ -1,92 +0,0 @@ -<script> - import { t } from "$lib/translations"; - import Icon from "$comp/Icon.svelte"; - import { page } from "$app/stores"; - - export let user; - $: paymentsUrl = - user.shopifyStore && - "https://admin.shopify.com/store/" + - user.shopifyStore + - "/settings/payments"; - $: checkoutUrl = - user.shopifyStore && - "https://admin.shopify.com/store/" + - user.shopifyStore + - "/settings/checkout"; - $: appsUrl = - user.shopifyStore && - "https://admin.shopify.com/store/" + - user.shopifyStore + - "/settings/apps/development"; - - let script = `<script src="${$page.url.protocol}//${$page.url.host}/${user.username}/shopify.js"><\/script>`; -</script> - -<div> - <label for="shopifyStore" class="font-bold mb-1 block">Store ID</label> - <div class="flex mb-2"> - <div - class="text-gray-600 p-4 my-auto bg-gray-100 border rounded-l-2xl border-r-0 pr-1" - > - admin.shopify.com/store/ - </div> - <input - type="text" - name="shopifyStore" - bind:value={user.shopifyStore} - class="border-l-0 rounded-l-none w-auto min-w-0 pl-1 grow" - /> - </div> - <p class="text-secondary my-2"> - Add Bitcoin under <a - class:active={!!paymentsUrl} - href={paymentsUrl || undefined}>Payments > Manual payment methods</a - > with a description like "Pay with Bitcoin". - </p> -</div> - -<div> - <label for="display" class="font-bold mb-1 block">Additional scripts</label> - <p class="text-secondary my-2"> - Copy this into <a class:active={!!paymentsUrl} href={checkoutUrl} - >Checkout -> Additional scripts</a - > - </p> - <textarea rows={5} type="text" name="shopifyScripts" readonly - >{script}</textarea - > -</div> - -<div> - <label for="shopifyToken" class="font-bold mb-1 block" - >Admin API token <span class="font-normal">(Optional)</span></label - > - <p class="text-secondary my-2"> - Coinos can automatically mark orders as Paid if you provide an API token. - <input - class="my-4" - type="text" - name="shopifyToken" - bind:value={user.shopifyToken} - /> - </p> - <p class="text-secondary my-2"> - Create a new app in <a class:active={!!appsUrl} href={appsUrl || undefined} - >Apps > App Development</a - > - </p> - - <p class="text-secondary my-2"> - Edit the Admin API scopes to enable <code class="text-black" - >write_orders</code - > permission then install the app into your store and copy the Admin API access - token here. - </p> -</div> - -<style> - .active { - @apply text-blue-500; - } -</style> |
